perm filename HALFTO.LST[UHF,DEK] blob
sn#841410 filedate 1987-06-15 generic text, type T, neo UTF8
1) HALFTO.WEB[UHF,DEK] and 2) OLDHAL.WEB[UHF,DEK] 6-15-87 23:16 pages 1,1
**** File 1) HALFTO.WEB[UHF,DEK]/1P/9L
1) C00028 00007 @* The main program.
1) C00029 00008 @* Index.
1) C00040 ENDMK
1) C⊗;
**** File 2) OLDHAL.WEB[UHF,DEK]/1P/9L
2) C00026 00007 @* The main program.
2) C00027 00008 @* Index.
2) C00038 ENDMK
2) C⊗;
***************
**** File 1) HALFTO.WEB[UHF,DEK]/3P/2L
1) This program prepares 33-level halftone images for use in \TeX\ files. The
1) input is assumed to be a sequence of pictures expressed in the form
**** File 2) OLDHAL.WEB[UHF,DEK]/3P/2L
2) This program prepares 65-level halftone images for use in \TeX\ files. The
2) input is assumed to be a sequence of pictures expressed in the form
***************
**** File 1) HALFTO.WEB[UHF,DEK]/3P/18L
1) for 33-level halftones, with ASCII characters |"0"| to |"P"| representing
1) darkness levels from white to black. The levels are adjusted to compensate
1) for the idiosyncrasies of Canon {\mc LBP-CX} laser-printing engines.
1) Two dots are typeset for each pixel of input; hence there are $2m$
1) ``half\/lines'' of $n$-character data in the output.
1) @ Here's an outline of the entire Pascal program:
**** File 2) OLDHAL.WEB[UHF,DEK]/3P/18L
2) for 65-level halftones, with ASCII characters |"0"| to |"p"| representing
2) darkness levels from white to black. The levels are adjusted to compensate
2) for the idiosyncrasies of Canon {\mc LBP-CX} laser-printing engines.
2) @ Here's an outline of the entire Pascal program:
***************
**** File 1) HALFTO.WEB[UHF,DEK]/4P/1L
1) @* The character set.
**** File 2) OLDHAL.WEB[UHF,DEK]/3P/52L
2) @ It's convenient to declare a macro for incrementation.
2) @d incr(#) == #←#+1
2) @* The character set.
***************
**** File 1) HALFTO.WEB[UHF,DEK]/5P/10L
1) @!v:array [0..max_m,0..max_n] of real; {pixel darknesses, from 0.0 to 1.0}
1) @!m:integer; {rows |0..m+1| of |v| should contain relevant data}
1) @!n:integer; {columns |0..n+1| of |v| should contain relevant data}
**** File 2) OLDHAL.WEB[UHF,DEK]/5P/10L
2) @!v:array [1..max_m,0..max_n] of real; {pixel darknesses, from 0.0 to 1.0}
2) @!m:integer; {rows |1..m+1| of |v| should contain relevant data}
2) @!n:integer; {columns |0..n+1| of |v| should contain relevant data}
***************
**** File 1) HALFTO.WEB[UHF,DEK]/5P/24L
1) program if anomalous values of |m| and~|n| occur. Boundary values are added
1) at the top, left, right, and bottom in order to provide ``padding'' that
1) will be convenient in the pixel transformation process. Each boundary value
1) is equal to one of its adjacent neighbors.
1) @<Input a picture, or terminate the program@>=
**** File 2) OLDHAL.WEB[UHF,DEK]/5P/24L
2) program if anomalous values of |m| and~|n| occur. Extra zeros are added
2) at the left, right, and bottom in order to provide ``padding'' that will
2) be convenient in the pixel transformation process.
2) @<Input a picture, or terminate the program@>=
***************
**** File 1) HALFTO.WEB[UHF,DEK]/5P/36L
1) v[i,0]:=v[i,1]; v[i,n+1]:=v[i,n];@/
1) read_ln;
1) end;
1) for j:=0 to n+1 do
1) begin v[0,j]:=v[1,j]; v[m+1,j]:=v[m,j];
1) end
1) @ The code just written makes use of three temporary registers that must
**** File 2) OLDHAL.WEB[UHF,DEK]/5P/35L
2) v[i,0]:=0.0; v[i,n+1]:=0.0;@/
2) read_ln;
2) end;
2) for j:=0 to n+1 do v[m+1,j]:=0.0
2) @ The code just written makes use of three temporary registers that must
***************
**** File 1) HALFTO.WEB[UHF,DEK]/6P/1L
1) @* Pixel compensation.
1) The 33-level output of this program is assumed to be printed by a font
1) that contains $4\times8$ characters, where each character has 0 to~32
1) black bits. Physical properties of output devices cause distortions,
1) so that a character with |k| black bits does not have an apparent
1) density of |k/32|. We therefore maintain a table of apparent density
1) values.
1) @d max_l=32 {maximum output level}
1) @<Glob...@>=
**** File 2) OLDHAL.WEB[UHF,DEK]/5P/46L
2) @!cc:ASCII_code; {ASCII equivalent of |c|}
2) @* Pixel compensation.
2) The 65-level output of this program is assumed to be printed by a font
2) that contains $8\times8$ characters, where each character has 0 to~64
2) black bits. Physical properties of output devices cause distortions,
2) so that a character with |k| black bits does not have an apparent
2) density of |k/64|. We therefore maintain a table of apparent density
2) values.
2) @d max_l=64 {maximum output level}
2) @<Glob...@>=
***************
**** File 1) HALFTO.WEB[UHF,DEK]/6P/16L
1) a page and the bottom; also blocks of the character |"N"| seem to appear
1) darker than blocks of the character |"O"|, because of some property of
1) xerography, although the |"O"| has one more bit turned on. Such
1) anomalies have been smoothed out here, since the resulting values should
**** File 2) OLDHAL.WEB[UHF,DEK]/6P/16L
2) a page and the bottom; also blocks of character |"n"| seem to appear
2) darker than blocks of the character |"o"|, because of some property of
2) xerography, although the |"o"| has one more bit turned on. Such
2) anomalies have been smoothed out here, since the resulting values should
***************
**** File 1) HALFTO.WEB[UHF,DEK]/6P/24L
1) d[1]:=0.06;
1) d[2]:=0.095;
1) d[3]:=0.125;
1) d[4]:=0.155;@/
1) d[5]:=0.175;
1) d[6]:=0.215;
1) d[7]:=0.245;
1) d[8]:=0.27;
1) d[9]:=0.29;@/
1) d[10]:=0.3;
1) d[11]:=0.31;
1) d[12]:=0.32;
1) d[13]:=0.33;
1) d[14]:=0.34;@/
1) d[15]:=0.35;
1) d[16]:=0.36;
1) d[17]:=0.37;
1) d[18]:=0.38;
1) d[19]:=0.4;@/
1) d[20]:=0.42;
1) d[21]:=0.44;
1) d[22]:=0.47;
1) d[23]:=0.5;
1) d[24]:=0.53;@/
1) d[25]:=0.57;
1) d[26]:=0.61;
1) d[27]:=0.66;
1) d[28]:=0.72;
1) d[29]:=0.80;@/
1) d[30]:=0.88;
1) d[31]:=0.96;
1) d[32]:=1.0;
1) @ We convert the pixel values by using a variant of the Floyd-Steinberg
**** File 2) OLDHAL.WEB[UHF,DEK]/6P/24L
2) d[1]:=0.03;
2) d[2]:=0.06;
2) d[3]:=0.08;
2) d[4]:=0.095;@/
2) d[5]:=0.11;
2) d[6]:=0.125;
2) d[7]:=0.14;
2) d[8]:=0.155;
2) d[9]:=0.17;@/
2) d[10]:=0.175;
2) d[11]:=0.2;
2) d[12]:=0.215;
2) d[13]:=0.23;
2) d[14]:=0.245;@/
2) d[15]:=0.26;
2) d[16]:=0.27;
2) d[17]:=0.28;
2) d[18]:=0.29;
2) d[19]:=0.295;@/
2) d[20]:=0.3;
2) d[21]:=0.305;
2) d[22]:=0.31;
2) d[23]:=0.315;
2) d[24]:=0.32;@/
2) d[25]:=0.325;
2) d[26]:=0.33;
2) d[27]:=0.335;
2) d[28]:=0.34;
2) d[29]:=0.345;@/
2) d[30]:=0.35;
2) d[31]:=0.355;
2) d[32]:=0.36;
2) d[33]:=0.365;
2) d[34]:=0.37;@/
2) d[35]:=0.375;
2) d[36]:=0.38;
2) d[37]:=0.39;
2) d[38]:=0.4;
2) d[39]:=0.41;@/
2) d[40]:=0.42;
2) d[41]:=0.43;
2) d[42]:=0.44;
2) d[43]:=0.455;
2) d[44]:=0.47;@/
2) d[45]:=0.485;
2) d[46]:=0.5;
2) d[47]:=0.515;
2) d[48]:=0.53;
2) d[49]:=0.55;@/
2) d[50]:=0.57;
2) d[51]:=0.59;
2) d[52]:=0.61;
2) d[53]:=0.635;
2) d[54]:=0.66;@/
2) d[55]:=0.685;
2) d[56]:=0.71;
2) d[57]:=0.74;
2) d[58]:=0.77;
2) d[59]:=0.8;@/
2) d[60]:=0.84;
2) d[61]:=0.88;
2) d[62]:=0.92;
2) d[63]:=0.96;
2) d[64]:=1.0;
2) @ We convert the pixel values by using a variant of the Floyd-Steinberg
***************
**** File 1) HALFTO.WEB[UHF,DEK]/6P/66L
1) in column~|j| of the current half\/line.
1) It outputs one 33-level density,
1) then updates |x| and~|j| in preparation for the next column.
1) Adjustments to the densities in the two next half\/lines are
1) accumulated in auxiliary arrays |next1| and |next2|; this will compensate
1) for errors in the current half\/line.
1) We assume that |next1[j]|, |next1[j+1]|, and |next2[j]| correspond to the
1) dots that are adjacent to |current[j]|.
1) @<Output one value and move to the next column@>=
**** File 2) OLDHAL.WEB[UHF,DEK]/6P/98L
2) in row~|i| and column~|j|. It outputs one 65-level density,
2) then updates |x| and~|j| in preparation for the next column in row~|i|.
2) Pixel values in row~|i+1| are modified to compensate for errors in
2) the current row.
2) @<Output one value and move to the next column@>=
***************
**** File 1) HALFTO.WEB[UHF,DEK]/6P/79L
1) next1[j]:=next1[j]+alpha*err;@/
1) next2[j]:=beta*err;@/
1) j←j+1; {move right}
1) next1[j]:=next1[j]+gamma*err;@/
1) x:=current[j]+delta*err
1) @ The constants |alpha..delta| control the distribution of errors to
1) adjacent dot positions.
1) @<Set init...@>=
1) alpha:=7/16; {error diffusion to SW neighbor}
1) beta:=1/16; {error diffusion to S neighbor}
1) gamma:=5/16; {error diffusion to SE neighbor}
1) delta:=3/16; {error diffusion to E neighbor}
1) @ Here is the overall control of the process.
1) Every half\/line of the picture being output is a sequence of ASCII characters
1) from |"0"| to |"P"|, terminated by |"."|.
1) @<Output the picture@>=
1) for j:=1 to n+1 do
1) begin next1[j]:=0.0; next2[j]:=0.0;
1) end;
1) for i:=1 to m do
1) begin @<Set the current half\/line data for the upper row of dots in line~|i|@>;
1) j:=1; x:=current[1];
1) repeat @<Output one value...@>;
**** File 2) OLDHAL.WEB[UHF,DEK]/6P/106L
2) v[i+1,j-1]:=v[i+1,j-1]+alpha*err;@/
2) v[i+1,j]:=v[i+1,j]+beta*err;@/
2) incr(j); {move right}
2) v[i+1,j]:=v[i+1,j]+gamma*err;@/
2) x:=v[i,j]+delta*err
2) @ Here is the overall control of the process.
2) Every line of the picture is a sequence of ASCII characters from |"0"| to |"p"|,
2) terminated by |"."|.
2) @<Output the picture@>=
2) for i:=1 to m do
2) begin j:=1; x:=v[i,1];
2) repeat @<Output one value...@>;
***************
**** File 1) HALFTO.WEB[UHF,DEK]/6P/108L
1) @<Set the current half\/line data for the lower row of dots in line~|i|@>;
1) j:=1; x:=current[1];
1) repeat @<Output one value...@>;
1) until j>n;
1) write_ln('.');
1) end
1) @ The density value for dot |j| in the upper half\/line of line~|i| is obtained
1) as a weighted average of the input values in rows |i-1| and~|i|, columns
1) |j| and~|j+1|. The upper half\/line is skewed to the right, so we must shift
1) |next1| and |next2| appropriately.
1) @<Set the current half\/line data for the upper row of dots in line~|i|@>=
1) for j←1 to n do
1) begin current[j]←(9*v[i,j]+3*v[i,j+1]+3*v[i-1,j]+v[i-1,j+1])/16
1) +next1[j+1];
1) next1[j]←next2[j];
1) end;
1) next1[n+1]←0.0
1) @ The lower half\/line is similar, but in this case there is leftward skew;
1) we use rows |i| and~|i+1|, columns |j-1| and~|j|.
1) @<Set the current half\/line data for the lower row of dots in line~|i|@>=
1) for j←1 to n do
1) begin current[j]←(9*v[i,j]+3*v[i,j-1]+3*v[i+1,j]+v[i+1,j-1])/16
1) +next1[j];
1) next1[j+1]←next2[j];
1) end;
1) next1[1]←0.0
1) @ The algorithm is now complete except for the part that chooses the
1) closest possible dot size. A straightforward binary search works well
1) for this purpose:
1) @<Find |l| so that |d[l]| is as close as possible to |x|@>=
**** File 2) OLDHAL.WEB[UHF,DEK]/6P/122L
2) end
2) @ It turns out to be desirable to
2) throw away about 10\% of the error. This dampens ``history'' effects
2) that the algorithm might otherwise introduce.
2) @<Set init...@>=
2) alpha:=3/18; {error diffusion to SW neighbor}
2) beta:=5/18; {error diffusion to S neighbor}
2) gamma:=1/18; {error diffusion to SE neighbor}
2) delta:=7/18; {error diffusion to E neighbor}
2) @ Here we use a straightforward binary search.
2) @<Find |l| so that |d[l]| is as close as possible to |x|@>=
***************
**** File 1) HALFTO.WEB[UHF,DEK]/6P/160L
1) @!current:array[0..max_n] of real; {desired densities in current half\/line}
1) @!next1,@!next2:array[0..max_n] of real; {corrections to subsequnt densities}
1) @!alpha,@!beta,@!gamma,@!delta:real; {constants of error diffusion}
**** File 2) OLDHAL.WEB[UHF,DEK]/6P/153L
2) @!alpha,@!beta,@!gamma,@!delta:real; {constants of error diffusion}
***************
**** File 1) HALFTO.WEB[UHF,DEK]/7P/5L
1) write_ln('\input hf33'); write_ln;
1) while true do
**** File 2) OLDHAL.WEB[UHF,DEK]/7P/5L
2) write_ln('\input halftone'); write_ln;
2) while true do
***************